﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using static System.Reflection.MethodBase;
using System.IO.Ports;
using System.Text;
using System.Windows;

namespace NhWeather.IO
{
    public class SPIO
    {

        /// <summary>
        /// 发送后，读函数前的等待时间
        /// </summary>
        private readonly int _sleepTime = 20;

        private readonly int _rTimeout = 20;

        private readonly int _wTimeout = 20;

        private readonly int _readBufferSize = 128;

        public string 握手帧 { get; set; } = string.Empty;

        /// <summary>
        /// IO名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 串口是否打开
        /// </summary>
        public bool Opened { get; set; }

        private SerialPort SP { get; set; }

        IIOListener IOListener { get; set; }

        /// <summary>
        /// 构造函数，从数据库中读出值成为函数参数
        /// </summary>
        public SPIO()
        {
            SP = new SerialPort()
            {
                StopBits = StopBits.Two,
                Parity = Parity.None,
                ReadTimeout = _rTimeout,
                WriteTimeout = _wTimeout,
                ReadBufferSize = _readBufferSize
            };

            Name = "串口";
        }

        /// <summary>
        /// 关闭服务
        /// </summary>
        /// <returns></returns>
        public bool Close()
        {
            if (Opened)
            {

                if (SP.IsOpen)
                {
                    SP.Close();
                    //IOListener.DisConnected(this, SP);
                }
                // IOListener.IOShutDown(this);
            }

            else Debug.WriteLine("串口已经关闭，不需要再次关闭");
            return true;
        }

        /// <summary>
        /// 打开串口
        /// </summary>
        /// <returns></returns>
        public bool Open(string portName, int baudRate = 9600)
        {
            bool result = false;

            SP.PortName = portName;
            SP.BaudRate = baudRate;

            try
            {
                SP.Open();
                //串口数据接受事件委托给自定义的方法处理
                SP.DataReceived += new SerialDataReceivedEventHandler(Received);
                result = true;
                if (握手帧.Length > 0)
                {
                    Send(Encoding.UTF8.GetBytes(握手帧));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"串口打开失败，{ex.Message}", "错误提示", MessageBoxButton.OK, MessageBoxImage.Error);
            }

            Opened = result;
            return result;
        }

        /// <summary>
        /// 设置IO监听器
        /// </summary>
        /// <param name="Listener"></param>
        public void SetIOListener(IIOListener Listener)
        {
            IOListener = Listener;
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="byt"></param>
        /// <returns></returns>
        public bool Send(byte[] byts)
        {
            bool result = false;
            Thread.Sleep(_sleepTime);

            try
            {
                SP.Write(byts, 0, byts.Length);
                result = true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"串口发送失败,{ex}");
            }
            return result;
        }

        /// <summary>
        /// 串口有数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Received(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            int length = sp.BytesToRead;
            byte[] buffer = new byte[length];
            try
            {
                sp.Read(buffer, 0, length);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"串口读取失败,{ex}");
            }
            IOListener.Received(buffer);
        }
    }
}
